#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#define NUM 1024

struct MyFILE_
{
    int fd;
    char buffer[NUM];
    int end; // 当前缓冲区结尾
};

typedef struct MyFILE_ MyFILE;

MyFILE* fopen_(const char* pathname,const char* mode)
{
    assert(pathname);
    assert(mode);
    MyFILE* fp = NULL;
    if(strcmp(mode,"r") == 0)
    {

    }
    else if(strcmp(mode,"r+") == 0)
    {

    }
    else if(strcmp(mode,"w") == 0)
    {
       int fd = open(pathname,O_CREAT | O_WRONLY | O_TRUNC,0666);
       if(fd >= 0)
       {
         fp = (MyFILE*)malloc(sizeof(MyFILE));
         memset(fp,0,sizeof(MyFILE));
         fp->fd = fd;
        
       }
    }
    else if(strcmp(mode,"w+") == 0)
    {

    }
    else if(strcmp(mode,"a") == 0)
    {

    }
    else if(strcmp(mode,"a+") == 0)
    {

    }

    return fp;
}

// 是不是应该是C标准库中的实现
void fputs_(const char* message,MyFILE* fp)
{
    assert(message);
    assert(fp);
    strcpy(fp->buffer+fp->end,message);
    fp->end += strlen(message);
    
    // for debug
    // printf("%s\n",fp->buffer);
    // 暂时没有刷新,刷新策略是由谁来执行的呢？用户通过执行C标准库中的代码逻辑，来完成刷新动作
    // 这里效率提高体现在哪里？因为C提供了缓冲区，那么我们就通过策略，减少了IO执行次数(不是数据量 )
    if(fp->fd == 0)
    {

    }
    else if(fp->fd == 1)
    {
        if(fp->buffer[fp->end - 1] == '\n')
        {
            fprintf(stderr,"%s",fp->buffer);
            write(fp->fd,fp->buffer,fp->end);
            fp->end = 0;
        }
    }
    else if(fp->fd == 2)
    {

    }
    else 
    {

    }
}

void fflush_(MyFILE* fp)
{

    assert(fp);
    if(fp->end != 0)
    {
        // 暂且认为刷新了--其实是把数据写到了内核里 sync把数据刷到磁盘
        write(fp->fd,fp->buffer,fp->end);
        syncfs(fp->fd);// 将数据写到磁盘
        fp->end = 0;
    }
}

void fclose_(MyFILE* fp)
{
    assert(fp);
    fflush_(fp);
    close(fp->fd);
    free(fp);
}

int main()
{
    close(1);
    MyFILE* fp = fopen_("log.txt","w");
    fputs_("hello one",fp);
    sleep(1);
    fputs_("hello two\n",fp);
    sleep(1);
    fputs_("hello three\n",fp);
    sleep(1);
    fputs_("hello four\n",fp);
    sleep(1);
    fclose_(fp);

    return 0;
}
